﻿using System;
using System.Collections.Generic;
using System.IO.MemoryMappedFiles;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ShareMemoryDemo
{
    public class SharedMemoryHelper
    {
        /// <summary>
        /// 将指定的内容写入到指定名称的共享内存。加入容错机制，写入失败返回false。
        /// </summary>
        /// <param name="key">内存块名称。</param>
        /// <param name="content">待写入的字符串内容。</param>
        /// <param name="mem_size">内存大小，默认为1MB。</param>
        public static bool WriteMemory(string key, string content, int mem_size = 1024 * 1024)
        {
            bool result = false;
            try
            {
                MemoryMappedFile mmfWrite = MemoryMappedFile.CreateOrOpen(key, mem_size);
                using (var accessor = mmfWrite.CreateViewAccessor())
                {
                    byte[] sourceBytes = Encoding.UTF8.GetBytes($"{content}\0");
                    byte[] memorySpace = new byte[mem_size];
                    for (int i = 0; i < sourceBytes.Length; i++)
                    {
                        memorySpace[i] = sourceBytes[i];
                        accessor.Write(i, ref memorySpace[i]);
                    }
                }
                result = true;
            }
            catch (Exception ex)
            {
                result = false;
                Console.WriteLine(ex.Message);
            }
            return result;
        }

        /// <summary>
        /// 使用指定的Key从共享内存中读取字符串。已加入容错机制，读取失败返回空字符串。
        /// </summary>
        /// <param name="key">内存块名称。</param>
        /// <param name="mem_size">内存大小，默认为1MB。</param>
        /// <returns></returns>
        public static string ReadMemory(string key, int mem_size = 1024 * 1024)
        {
            StringBuilder content = new StringBuilder();
            try
            {
                MemoryMappedFile mmfRead = MemoryMappedFile.CreateOrOpen(key, mem_size);
                using (var accessor = mmfRead.CreateViewAccessor())
                {
                    byte[] memorySpace = new byte[accessor.Capacity];
                    for (int i = 0; i < memorySpace.Length; i++)
                        memorySpace[i] = accessor.ReadByte(i);

                    int end = 0;
                    for (int i = 0; i < memorySpace.Length; i++)
                    {
                        if (memorySpace[i] == '\0')
                        {
                            end = i;
                            break;
                        }
                    }

                    content.Append(Encoding.UTF8.GetString(memorySpace, 0, end));
                }
            }
            catch (Exception ex) { Console.WriteLine(ex.Message); }
            return content.ToString();
        }

    }
}
